using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using log4net;
using Triton.Common.LogUtilities;
using Triton.Game.Mapping;

namespace Triton.Game
{
	public static class MappingExtensions
	{
		private static readonly ILog ilog_0 = Triton.Common.LogUtilities.Logger.GetLoggerInstanceForType();

		public static int GetRealTimeRemainingHP(this Card @this)
		{
			return @this.GetEntity().GetRealTimeRemainingHP();
		}

		public static int GetRealTimeAttack(this Card @this)
		{
			return @this.GetEntity().GetRealTimeAttack();
		}

		public static int GetRealTimeCost(this Card @this)
		{
			return @this.GetEntity().GetRealTimeCost();
		}

		public static bool HasTaunt(this Card @this)
		{
			if (!@this.GetEntity().IsMinion())
			{
				return false;
			}
			if (@this.GetZone() == GameState.Get().GetFriendlySidePlayer().GetHandZone())
			{
				return @this.GetEntity().HasTaunt();
			}
			if (@this.GetActor() != null && (@this.GetActor().IsSpellActive(SpellType.TAUNT) || @this.GetActor().IsSpellActive(SpellType.TAUNT_PREMIUM)))
			{
				return true;
			}
			return false;
		}

		public static List<Card> FindAdjacentMinions(this Card @this)
		{
			Zone zone = @this.GetZone();
			int zonePosition = @this.GetZonePosition();
			Card cardAtPos = zone.GetCardAtPos(zonePosition - 1);
			Card cardAtPos2 = zone.GetCardAtPos(zonePosition + 1);
			List<Card> list = new List<Card>();
			if (cardAtPos != null)
			{
				list.Add(cardAtPos);
			}
			if (cardAtPos2 != null)
			{
				list.Add(cardAtPos2);
			}
			return list;
		}

		public static async Task DoGrab(this Card @this)
		{
			Vector3 center = Client.CardInteractPoint(@this);
			await Client.MoveCursorHumanLike(center);
			Client.LeftClickAt(center);
		}

		public static async Task DoTargeting(this Card @this, Card target)
		{
			Vector3 center = Client.CardInteractPoint(target);
			await Client.MoveCursorHumanLike(center);
			Client.LeftClickAt(center);
		}

		public static void Cancel(this Card @this)
		{
			Client.RightClickAt(Client.CardInteractPoint(@this));
		}

		public static async Task DoAttack(this Card @this, Card attackee)
		{
			using (TritonHs.Memory.TemporaryCacheState(enabledTemporarily: false))
			{
				Vector3 center = Client.CardInteractPoint(@this);
				Vector3 center2 = Client.CardInteractPoint(attackee);
				await Client.MoveCursorHumanLike(center);
				Client.LeftClickAt(center);
				Stopwatch stopwatch = Stopwatch.StartNew();
				while (!TargetReticleManager.Get().IsActive())
				{
					using (TritonHs.Memory.ReleaseFrame(reacquireAsHardLock: true))
					{
						Thread.Sleep(10);
					}
					if (stopwatch.ElapsedMilliseconds > 500L)
					{
						ilog_0.ErrorFormat("[DoAttack] {0} elapsed and no card was picked up to attack with.", stopwatch.ElapsedMilliseconds);
						return;
					}
				}
				await Client.MoveCursorHumanLike(center2);
				Client.LeftClickAt(center2);
			}
		}

		public static string GetCardId(this Card @this)
		{
			return @this.GetEntity().GetCardId();
		}

		public static bool HasCharge(this Card @this)
		{
			return @this.GetEntity().HasCharge();
		}

		public static bool ReferencesCharge(this Card @this)
		{
			return @this.GetEntity().ReferencesCharge();
		}

		public static bool HasBattlecry(this Card @this)
		{
			return @this.GetEntity().HasBattlecry();
		}

		public static bool ReferencesBattlecry(this Card @this)
		{
			return @this.GetEntity().ReferencesBattlecry();
		}

		public static bool CanBeTargetedBySpells(this Card @this)
		{
			return @this.GetEntity().CanBeTargetedBySpells();
		}

		public static bool CanBeTargetedByHeroPowers(this Card @this)
		{
			return @this.GetEntity().CanBeTargetedByHeroPowers();
		}

		public static bool HasTriggerVisual(this Card @this)
		{
			return @this.GetEntity().HasTriggerVisual();
		}

		public static bool IsImmune(this Card @this)
		{
			return @this.GetEntity().IsImmune();
		}

		public static bool IsPoisonous(this Card @this)
		{
			return @this.GetEntity().IsPoisonous();
		}

		public static bool HasHealthMin(this Card @this)
		{
			return @this.GetEntity().HasHealthMin();
		}

		public static bool ReferencesImmune(this Card @this)
		{
			return @this.GetEntity().ReferencesImmune();
		}

		public static bool IsEnraged(this Card @this)
		{
			return @this.GetEntity().IsEnraged();
		}

		public static bool IsFreeze(this Card @this)
		{
			return @this.GetEntity().IsFreeze();
		}

		public static int GetDamage(this Card @this)
		{
			return @this.GetEntity().GetDamage();
		}

		public static bool IsFrozen(this Card @this)
		{
			return @this.GetEntity().IsFrozen();
		}

		public static bool IsStealthed(this Card @this)
		{
			return @this.GetEntity().IsStealthed();
		}

		public static bool ReferencesStealth(this Card @this)
		{
			return @this.GetEntity().ReferencesStealth();
		}

		public static bool ReferencesTaunt(this Card @this)
		{
			return @this.GetEntity().ReferencesTaunt();
		}

		public static bool HasDivineShield(this Card @this)
		{
			return @this.GetEntity().HasDivineShield();
		}

		public static bool ReferencesAutoAttack(this Card @this)
		{
			return @this.GetEntity().ReferencesAutoAttack();
		}

		public static bool ReferencesDivineShield(this Card @this)
		{
			return @this.GetEntity().ReferencesDivineShield();
		}

		public static bool IsHero(this Card @this)
		{
			return @this.GetEntity().IsHero();
		}

		public static bool IsHeroPower(this Card @this)
		{
			return @this.GetEntity().IsHeroPower();
		}

		public static bool IsMinion(this Card @this)
		{
			return @this.GetEntity().IsMinion();
		}

		public static bool IsSpell(this Card @this)
		{
			return @this.GetEntity().IsSpell();
		}

		public static bool IsWeapon(this Card @this)
		{
			return @this.GetEntity().IsWeapon();
		}

		public static bool IsElite(this Card @this)
		{
			return @this.GetEntity().IsElite();
		}

		public static bool IsGame(this Card @this)
		{
			return @this.GetEntity().IsGame();
		}

		public static bool IsPlayer(this Card @this)
		{
			return @this.GetEntity().IsPlayer();
		}

		public static bool IsEnchantment(this Card @this)
		{
			return @this.GetEntity().IsEnchantment();
		}

		public static bool IsExhausted(this Card @this)
		{
			return @this.GetEntity().IsExhausted();
		}

		public static bool IsAttached(this Card @this)
		{
			return @this.GetEntity().IsAttached();
		}

		public static bool IsRecentlyArrived(this Card @this)
		{
			return @this.GetEntity().IsRecentlyArrived();
		}

		public static bool IsSecret(this Card @this)
		{
			return @this.GetEntity().IsSecret();
		}

		public static bool ReferencesSecret(this Card @this)
		{
			return @this.GetEntity().ReferencesSecret();
		}

		public static bool CanAttack(this Card @this)
		{
			return @this.GetEntity().CanAttack();
		}

		public static bool CanBeAttacked(this Card @this)
		{
			return @this.GetEntity().CanBeAttacked();
		}

		public static bool CanBeTargetedByOpponents(this Card @this)
		{
			return @this.GetEntity().CanBeTargetedByOpponents();
		}

		public static bool IsMagnet(this Card @this)
		{
			return @this.GetEntity().IsMagnet();
		}

		public static int GetNumTurnsInPlay(this Card @this)
		{
			return @this.GetEntity().GetNumTurnsInPlay();
		}

		public static int GetNumAttacksThisTurn(this Card @this)
		{
			return @this.GetEntity().GetNumAttacksThisTurn();
		}

		public static int GetSpellPower(this Card @this)
		{
			return (int)@this.GetEntity().GetSpellPowerSchool();
		}

		public static bool HasSpellPower(this Card @this)
		{
			return @this.GetEntity().HasSpellPower();
		}

		public static bool IsAffectedBySpellPower(this Card @this)
		{
			return @this.GetEntity().IsAffectedBySpellPower();
		}

		public static bool HasSpellPowerDouble(this Card @this)
		{
			return @this.GetEntity().HasSpellPowerDouble();
		}

		public static bool ReferencesSpellPower(this Card @this)
		{
			return @this.GetEntity().ReferencesSpellPower();
		}

		public static int GetCost(this Card @this)
		{
			return @this.GetEntity().GetCost();
		}

		public static int GetATK(this Card @this)
		{
			return @this.GetEntity().GetATK();
		}

		public static int GetAttached(this Card @this)
		{
			return @this.GetEntity().GetAttached();
		}

		public static int GetDurability(this Card @this)
		{
			return @this.GetEntity().GetDurability();
		}

		public static int GetArmor(this Card @this)
		{
			return @this.GetEntity().GetArmor();
		}

		public static int GetCreatorId(this Card @this)
		{
			return @this.GetEntity().GetCreatorId();
		}

		public static int GetControllerId(this Card @this)
		{
			return @this.GetEntity().GetControllerId();
		}

		public static int GetFatigue(this Card @this)
		{
			return @this.GetEntity().GetFatigue();
		}

		public static int GetWindfury(this Card @this)
		{
			return @this.GetEntity().GetWindfury();
		}

		public static bool HasWindfury(this Card @this)
		{
			return @this.GetEntity().HasWindfury();
		}

		public static bool ReferencesWindfury(this Card @this)
		{
			return @this.GetEntity().ReferencesWindfury();
		}

		public static bool HasCombo(this Card @this)
		{
			return @this.GetEntity().HasCombo();
		}

		public static bool HasOverload(this Card @this)
		{
			return @this.GetEntity().HasOverload();
		}

		public static bool HasDeathrattle(this Card @this)
		{
			return @this.GetEntity().HasDeathrattle();
		}

		public static bool ReferencesDeathrattle(this Card @this)
		{
			return @this.GetEntity().ReferencesDeathrattle();
		}

		public static bool IsSilenced(this Card @this)
		{
			return @this.GetEntity().IsSilenced();
		}

		public static int GetEntityId(this Card @this)
		{
			return @this.GetEntity().GetEntityId();
		}

		public static bool IsCharacter(this Card @this)
		{
			return @this.GetEntity().IsCharacter();
		}

		public static bool IsItem(this Card @this)
		{
			return @this.GetEntity().IsItem();
		}

		public static bool IsToken(this Card @this)
		{
			return @this.GetEntity().IsToken();
		}

		public static bool CanBeDamagedRealTime(this Card @this)
		{
			return @this.GetEntity().CanBeDamagedRealTime();
		}

		public static int GetHealth(this Card @this)
		{
			return @this.GetEntity().GetHealth();
		}

		public static TAG_RACE GetRace(this Card @this)
		{
			return @this.GetEntity().GetRace();
		}

		public static List<Entity> GetAttachments(this Card @this)
		{
			return @this.GetEntity().GetAttachments();
		}

		public static string GetName(this Card @this)
		{
			return @this.GetEntity().GetName();
		}

		public static TAG_RARITY GetRarity(this Card @this)
		{
			return @this.GetEntity().GetRarity();
		}

		public static bool IsEnchanted(this Card @this)
		{
			return @this.GetEntity().IsEnchanted();
		}

		public static bool CanBeTargeted(this Card @this)
		{
			Actor actor = @this.GetActor();
			if (actor == null)
			{
				return false;
			}
			if (actor.GetActorStateType() != ActorStateType.CARD_VALID_TARGET)
			{
				return actor.GetActorStateType() == ActorStateType.CARD_VALID_TARGET_MOUSE_OVER;
			}
			return true;
		}

		public static bool CanBeUsed(this Card @this)
		{
			Actor actor = @this.GetActor();
			if (actor == null)
			{
				return false;
			}
			if (actor.GetActorStateType() != ActorStateType.CARD_PLAYABLE && actor.GetActorStateType() != ActorStateType.CARD_COMBO && actor.GetActorStateType() != ActorStateType.CARD_PLAYABLE_MOUSE_OVER)
			{
				return actor.GetActorStateType() == ActorStateType.CARD_COMBO_MOUSE_OVER;
			}
			return true;
		}
	}
}
